#include "server.h"
#include "aikit/aikit.h"

std::shared_ptr<server> server::Server;
task server::thisTask;

server::server()
{
    AEE_Init();
}

server::~server()
{
    AIKIT_UnInit();
}

bool server::initServer(const unsigned short in_port)
{
    m_port = in_port;

    // sigset_t signal_mask;
    // sigemptyset(&signal_mask);
    // sigaddset(&signal_mask,SIGPIPE);
    // pthread_sigmask(SIG_BLOCK,&signal_mask,NULL);

    struct sigaction sa;
    sa.sa_handler = SIG_IGN;
    sigaction(SIGPIPE, &sa, NULL);
    // 第1步：创建服务端的socket。
    if ((m_listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        std::cout << "m_listenfd socket error" << std::endl;
        return false;
    }

    // 第2步：把服务端用于通信的地址和端口绑定到socket上。
    struct sockaddr_in servaddr; // 服务端地址信息的数据结构。
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;                // 协议族，在socket编程中只能是AF_INET。
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // 任意ip地址。
    servaddr.sin_port = htons(in_port);           // 指定通信端口。

    // 绑定服务器的IP地址和端口
    if (bind(m_listenfd, reinterpret_cast<sockaddr*>(&servaddr), sizeof(servaddr)) != 0)
    {
        perror("bind");
        m_listenfd = -1;
        return false;
    }

    // 第3步：把socket设置为监听模式。
    if (listen(m_listenfd, CLIENT_MAX_NUM) != 0)
    {
        perror("listen");
        m_listenfd = -1;
        return false;
    }
    for (int i = 0; i < CLIENT_MAX_NUM; i++)
    {
        threads.push_back(std::thread(&server::threadProc, this));
    }

    while (true)
    {

        int fd = acceptingConnections();

        if (fd <= 0)
            continue;

        task _t;
        _t.fd = fd;
        AddTask(_t);
    }

    return true;
}

void server::AddTask(task t)
{
    std::lock_guard<std::mutex> _locker(lock);
    tasks.push_back(t);
}

void server::threadProc()
{
    while (true)
    {
        task _t;

        std::this_thread::sleep_for(std::chrono::milliseconds(400));
        {
            std::lock_guard<std::mutex> _locker(lock);
            if (tasks.empty())
            {
                continue;
            }
            _t = tasks.front();
            tasks.pop_front();
        }

        while (true)
        {
            // 1,接受头
            Head head;
            int readn = recvMessage(reinterpret_cast<uint8_t*>(&head), _t.fd, sizeof(Head));
            if (readn < 0)
            {
                std::cout << "recv len fail" << std::endl;
                break;
            } else if(readn == 0) {
                std::cout << "socket close" << std::endl;
                break;
            }
            std::cout << "Head Len:" << head.Len << std::endl;

            // 2，接受payload
            std::shared_ptr<uint8_t[]> recvBuffer(new uint8_t[head.Len+1]);
            recvBuffer[head.Len-1] = '\0';

            readn = recvMessage(recvBuffer.get(), _t.fd, head.Len);
            if (readn < 0)
            {
                std::cout << "recv len fail" << std::endl;
                break;
            } else if(readn == 0) {
                std::cout << "socket close" << std::endl;
                break;
            }
            std::cout << "recv text :" << recvBuffer << std::endl;

            // 3，处理数据
            lock_ttex.lock();
            thisTask = _t;
            std::string text = reinterpret_cast<char*>(recvBuffer.get());
            XTTS_Stream(text);
            lock_ttex.unlock();

        }
        close(_t.fd);
    }
}

int server::acceptingConnections()
{
    // 第4步：接受客户端的连接
    int socklen = sizeof(struct sockaddr_in); // struct sockaddr_in的大小
    struct sockaddr_in clientaddr;            // 客户端的地址信息。
    int fd;
    if ((fd = accept(m_listenfd, (struct sockaddr *)&clientaddr, (socklen_t *)&socklen)) == -1)
    {
        std::cout << "acceptingConnections fail !" << std::endl;
        return -1;
    }
    int _f = fcntl(fd, F_GETFL, 0);
    fcntl(fd, F_SETFL, _f | O_NONBLOCK);
    printf("服务器与客户端（%s）建立连接。\n", inet_ntoa(clientaddr.sin_addr));
    return fd;
}

int server::recvMessage(uint8_t* buffer, int fd, int bufferSize)
{
    int sum = 0;
    auto t1 = std::chrono::system_clock::now();
    while (true)
    {
        int _l = (bufferSize - sum) > MAX_EACH_SIZE ? MAX_EACH_SIZE : (bufferSize - sum);
        int readn = recv(fd, buffer + sum, _l, 0);

        if (readn == 0)
        {
            return readn;
        }

        if (readn < 0)
        {
            if (errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR)
            {
                auto t2 = std::chrono::system_clock::now();
                auto duration = std::chrono::duration_cast<std::chrono::seconds>(t2 - t1);
                if (duration.count() > 60*30)
                {
                    return readn;
                }
                continue;
            }
            else
                return readn;
        }

        sum += readn;
        if (sum == bufferSize)
            return sum;
    }
}

bool server::sendMessage(uint8_t* buffer, int fd, int bufferSize)
{

    int oneSend = 0;
    int totalBytes = 0;

    auto t1 = std::chrono::system_clock::now();
    while (true)
    {

        oneSend = (bufferSize - totalBytes) > MAX_EACH_SIZE ? MAX_EACH_SIZE : (bufferSize - totalBytes);

        int sendn = send(fd, buffer + totalBytes, oneSend, 0);
        if (sendn == 0)
        {
            return false;
        }

        if (sendn < 0)
        {
            if (errno == EWOULDBLOCK || errno == EAGAIN || errno == EINTR)
            {
                auto t2 = std::chrono::system_clock::now();
                auto duration = std::chrono::duration_cast<std::chrono::seconds>(t2 - t1);
                if (duration.count() > 60*30)
                {
                    return false;
                }
                continue;
            }
            else
            {
                return false;
            }
        }

        totalBytes += sendn;
        if (totalBytes == bufferSize)
            break;
    }

    return true;
}

bool server::sendFile(const std::string &fileName, int fd, int headLen)
{

    int onread = 0;
    int totalbytes = 0;

    FILE *file = fopen(fileName.c_str(), "rb");

    if (!file)
    {
        std::cout << "file null" << std::endl;
        return false;
    }

    uint8_t buffer[MAX_BUFFER_SIZE];

    while (true)
    {

        if (headLen - totalbytes > MAX_BUFFER_SIZE)
        {
            onread = MAX_BUFFER_SIZE;
        }
        else
        {
            onread = headLen - totalbytes;
        }

        int readn;
        if ((readn = fread(buffer, sizeof(uint8_t), onread, file)) <= 0)
        {
            fclose(file);
            remove(fileName.c_str());
            return false;
        }

        if (!sendMessage(buffer, fd, readn))
        {
            fclose(file);
            remove(fileName.c_str());
            return false;
        }

        totalbytes += readn;

        if (totalbytes == headLen)
        {
            break;
        }
    }

    fclose(file);
    remove(fileName.c_str());

    return true;
}

std::string server::GenerateRandomString(size_t length)
{
    const char charset[] =
        "0123456789"
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "abcdefghijklmnopqrstuvwxyz";
    const size_t max_index = (sizeof(charset) - 1);
    std::string str(length, 0);
    std::default_random_engine engine(static_cast<unsigned int>(time(nullptr)));
    std::uniform_int_distribution<> distribution(0, max_index);

    for (size_t i = 0; i < length; ++i)
    {
        str[i] = charset[distribution(engine)];
    }

    return str;
}